import gleam/int
import gleam/io
import gleam/list
import gleam/string as text

pub fn stage2_test() -> Int {
  old_function()
  // warnning as deprecated
  new_function()

  let x = int.random(5)
  io.debug(x)
  // Case expression
  let result = case x {
    0 -> "Zero"
    1 -> "One"
    _ -> "Other"
  }

  io.debug(result)

  let result = case int.random(5) {
    0 -> "Zero"
    1 -> "One"
    other -> "It is " <> int.to_string(other)
  }

  io.debug(result)
  // String Pattern match
  io.debug(get_name("Hello, Joe"))
  io.debug(get_name("Hello, Mike"))
  io.debug(get_name("anyway"))
  // List Pattern match
  let x = list.repeat(int.random(5), times: int.random(3))
  // swift labeled parameter
  io.debug("x : ")
  io.debug(x)

  let result = case x {
    [] -> "Empty list"
    [1] -> "[1]"
    [4, ..] -> "start with 4"
    [_, _] -> "list has two elements"
    _ -> {
      io.debug("match: ")
      io.debug(x)
      "Some other list"
    }
  }

  io.debug("result: ")
  io.debug(result)
  // Recursion
  io.debug(factorial(0))
  io.debug(factorial(1))
  io.debug(factorial(6))
  // Tail Calls
  io.debug(f(5))
  io.debug(f(0))
  io.debug(f(1))
  // List recursion
  let sum = sum_list([1, 19, 29, 39, 19, 29], result: 0)
  io.debug(sum)

  // Alternative pattern
  let number = int.random(10)
  io.debug("random number is : ")
  io.debug(number)

  let result = case number {
    0 | 2 | 4 | 6 | 8 -> "even number"
    1 | 3 | 5 | 7 | 9 -> "odd number"
    _ -> "I'm not sure the number"
  }

  io.debug(result)

  // Pattern aliases and generic
  io.debug(get_first_non_empty(g_list: [[], [1, 2, 3], [4, 5]]))
  io.debug(get_first_non_empty(g_list: [[1, 2], [3, 4, 5], []]))
  io.debug(get_first_non_empty(g_list: [[], [], []]))

  let numbers = [1, 2, 3, 4, 5]
  io.debug(get_first_larger(numbers, level: 3))
  // print 4
  io.debug(get_first_larger(numbers, level: 5))
  // print 0

  2
}

fn get_first_larger(numbers: List(Int), level limit: Int) -> Int {
  case numbers {
    [first, ..] if first > limit -> first
    [_, ..rest] -> get_first_larger(rest, level: limit)
    [] -> 0
  }
}

fn get_first_non_empty(g_list lists: List(List(t))) -> List(t) {
  case lists {
    [[_, ..] as first, ..] -> first
    [_, ..rest] -> get_first_non_empty(g_list: rest)
    [] -> []
  }
}

fn sum_list(list: List(Int), result total: Int) -> Int {
  case list {
    [first, ..rest] -> sum_list(rest, total + first)
    // pop the first and process the rest recursive
    [] -> total
  }
}

pub fn f(x: Int) -> Int {
  factorial_loop(x, 1)
}

fn factorial_loop(x: Int, accumulator: Int) -> Int {
  case x {
    0 -> accumulator
    1 -> accumulator

    _ -> factorial_loop(x - 1, accumulator * x)
  }
}

fn factorial(x: Int) -> Int {
  case x {
    0 -> 1
    1 -> 1

    _ -> x * factorial(x - 1)
  }
}

fn get_name(x: String) -> String {
  case x {
    // when args match `"Hello, <name>"
    "Hello, " <> name -> name
    _ -> "Unknown fucker"
  }
}

@deprecated("Use new_function() instead")
fn old_function() {
  Nil
}

fn new_function() {
  Nil
}
